package com.sanyue.springboot;

import com.sanyue.springboot.bean.Cat;
import com.sanyue.springboot.bean.Dog;
import com.sanyue.springboot.bean.Monster;
import com.sanyue.springboot.bean.People;
import com.sanyue.springboot.config.BeanConfig;
import org.junit.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 *  解读：
 *   1.@SpringBootApplication：表示这是一个SpringBoot应用/项目
 *   2.运行项目就是运行main函数
 *   3.运行成功后：可以看出端口号8080，且上下文路径为空，即localhost:8080/项目路径
 *     o.s.b.w.embedded.tomcat.TomcatWebServer  :
 *     Tomcat started on port(s): 8080 (http) with context path ''
 *   4.@SpringBootApplication(scanBasePackages = "com.sanyue")：指定springboot扫描com.sanyue包及其子包的文件
 *     scanBasePackages的类型为数组，单当只有一个值时，可以不添加大括号{}
 */
@SpringBootApplication(scanBasePackages = "com.sanyue")
public class MainApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);

        //查看容器内部的组件（bean）
          //1.debug查看单例池
          //2.ioc.getBeanDefinitionNames();循环输出内部bean
        //查看输出非常之多，例如：beanDefinitionName = characterEncodingFilter，字符集过滤，处理中文乱码问题
        // String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
        // for (String beanDefinitionName : beanDefinitionNames) {
        //     System.out.println("beanDefinitionName = " + beanDefinitionName);
        // }

        //判断容器中是否注入一个bean
        // boolean b = ioc.containsBean("monster05");
        // System.out.println("b = " + b);


        //Spring的注解SpringBoot仍然可以使用，不予演示


        //测试springboot项目仍然可以使用spring的传统方式配置bean
        // ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        // Monster monster = ac.getBean("monster03", Monster.class);
        // System.out.println("monster = " + monster);

        //演示 @Configuration方式配置bean
        // Monster monster01 = ioc.getBean("monster01", Monster.class);
        // Monster monster01Again = ioc.getBean("monster01", Monster.class);
        // System.out.println(monster01Again == monster01);

        //配置类也会注入到容器中
        // BeanConfig bean = ioc.getBean(BeanConfig.class);
        // System.out.println("bean = " + bean);


        //演示@Configuration(proxyBeanMethods = xxx)的使用
        //1.先获得BeanConfig组件
        //注意：@Scope("prototype") --> 这个注解需要注销掉
        //true -> 单实例：获取到的BeanConfig对象是代理对象
        //false -> 多实例：获取到的BeanConfig对象是正常对象
        // BeanConfig beanConfig = ioc.getBean(BeanConfig.class);
        // Monster monster_01 = beanConfig.monster01();
        // Monster monster_02 = beanConfig.monster01();
        // System.out.println("monster_01 = " + monster_01.hashCode());
        // System.out.println("monster_02 = " + monster_02.hashCode());
        // System.out.println(monster_02 == monster_01);

        //注意小细节proxyBeanMethods 是在 调用@Bean 方法 才生效，因此，需要先获取
        //BeanConfig 组件，再调用方法。
        //而不是直接通过 SpringBoot 主程序得到的容器来获取 bean, 注意观察直接通过
        //ioc.getBean() 获取 Bean, proxyBeanMethods 值并没有生效
        //这里如果proxyBeanMethods=false生效了，则显示false。但是本段代码输出为true
        // Monster monster = ioc.getBean("monster01", Monster.class);
        // Monster monster2 = ioc.getBean("monster01", Monster.class);
        // System.out.println(monster2 == monster);


        //测试可以有多个配置类
        // Monster monster02 = ioc.getBean("monster02", Monster.class);
        // Monster monster01 = ioc.getBean("monster01", Monster.class);
        // System.out.println("monster01 = " + monster01);
        // System.out.println("monster02 = " + monster02);、

        //测试通过@Import组件引入的bean
        //beanDefinitionName = com.sanyue.springboot.bean.Cat
        //beanDefinitionName = com.sanyue.springboot.bean.Dog
        // Cat cat = ioc.getBean(Cat.class);
        // Dog dog = ioc.getBean(Dog.class);
        // System.out.println("dog = " + dog);
        // System.out.println("cat = " + cat);


        //测试@Conditional注解——条件装配
        //注意：需要将@Import注解去掉，否则会报错
        // Dog dog = ioc.getBean(Dog.class);
        // System.out.println("dog = " + dog);


        //测试@ImportResource注解——BeanConfig3
        // Monster monster = ioc.getBean("monster05", Monster.class);
        // System.out.println("monster = " + monster);

        //配置绑定第二种方法测试
        People bean = ioc.getBean(People.class);
        System.out.println("bean = " + bean);

    }


}
